import { Component, h, render } from "vue"
import { ref, Ref, ExtractPropTypes } from "vue"
import Index from './ModalMessage.vue'
// import { componentProps } from './props'

export interface PropsType {
  visible: Ref<boolean>;
  title: string;
  content: string;
  type: 'success' | 'error' | 'warning';
  confirm?: () => void;
  cancel?: () => void;
  [x: string]: any
}

/**
 * 渲染组件实例
 * @param Constructor 组件
 * @param props 组件参数
 * @returns 组件实例
 */
export const renderInstance = (Constructor: Component, props: Record<string, any>) => {
  // 创建组件容器, 这一步是必须的, 在销毁组件时会使用到
  const container = document.createElement('div')

  // 在 props 添加组件消失钩子, 移除当前实例, 将销毁方法提供给组件
  // 这里不需要调用 document.body.removeChild(container.firstElementChild)
  // 因为调用 render(null, container) 为我们完成了这项工作
  props.vanish = () => {
    render(null, container)
  }

  // 创建虚拟节点, 渲染组件
  const vnode = h(Constructor, props)
  render(vnode, container)

  // 添加子元素(组件)至父元素
  document.body.appendChild(container.firstElementChild as HTMLDivElement)
}


/** 组件 Props 类型, ExtractPropTypes 可将 Constructor 转换为对应值类型 */
type Props = ExtractPropTypes<PropsType>

/** 组件调用 resolve 返回结果 */
type Result = { path: string }[]

/**
 * 模态框调用方法
 * @param props 
 * @returns {Promise}
 */
export const ModalMessage = (props: Props) => {
  return new Promise<Result>((resolve, reject) => {
    renderInstance(Index, {
      // 这里 visible, 为了使组件可修改, 需要传入 ref
      // 注意这块地方，我们将这个值设置为 true 为了调起即直接展示组件
      visible: ref(true),
      ...props, resolve, reject
    })
  })
}